#include <iostream>
#include <vector>
#include <utility>

#include "GLee.h"
#include <GL/glu.h>

#include "MainMenu.h"
#include "MyWindow.h"
#include "Button.h"
#include "FontManager.h"
#include "Background.h"
#include "Game.h"
#include "KingPigFactory.h"
#include "AudioSource.h"
#include "OptionsScreen.h"
#include "SimplePigFactory1.h"
#include "FreeTypeFont.h"

using namespace std;

MainMenu::MainMenu(MyWindow* window)
: Scene(window), m_arcadeBtn(NULL), m_survivalBtn(NULL), m_optionsBtn(NULL), m_exitBtn(NULL),
m_background(NULL), m_bgm(NULL)
{
}

MainMenu::~MainMenu(void)
{
}

bool MainMenu::init()
{
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);

    //Viewport[2] stores the width of the viewport, vieport[3] stores the height
    //We pass these into our font so the ortho mode can set the resolution for the window
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    // Initialize the font
    FontManager* fontManager = FontManager::getInstance();
    if (fontManager->hasFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 60)))
    {
        m_font = fontManager->getFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 60));
    }
    else
    {
        m_font = boost::shared_ptr<FreeTypeFont>(new FreeTypeFont("data/textures/ANGRY_BIRDS.ttf",
                              viewport[2], 
                              viewport[3], 
                              60));
        fontManager->addFont(m_font);
    }

    // Initialize the background
    m_background = new Background("data/textures/background8.tga");
    if (!m_background->initialize()) {
        std::cerr << "Could not initialize the background" << std::endl;
        return false;
    }

    // Initialize arcade button
    m_arcadeBtn = new Button(boost::shared_ptr<Scene>(this));
    m_arcadeBtn->setDimension(Dimension(148.0f, 42.0f));
    m_arcadeBtn->setPosition(Vector3(viewport[2]/2.0f, 300.0f, 0.0f));
    if (!m_arcadeBtn->initialize()) {
        std::cerr << "Could not initialize the Arcade Button" << std::endl;
        return false;
    }
    m_arcadeBtn->setFontSize(24);
    m_arcadeBtn->setLabel("ARCADE ");

    // Initialize survival button
    m_survivalBtn = new Button(boost::shared_ptr<Scene>(this));
    m_survivalBtn->setDimension(Dimension(148.0f, 42.0f));
    m_survivalBtn->setPosition(Vector3(viewport[2]/2.0f, 250.0f, 0.0f));
    if (!m_survivalBtn->initialize()) {
        std::cerr << "Could not initialize the Survival Button" << std::endl;
        return false;
    }
    m_survivalBtn->setFontSize(24);
    m_survivalBtn->setLabel("SURVIVAL ");

    // Initialize options button
    m_optionsBtn = new Button(boost::shared_ptr<Scene>(this));
    m_optionsBtn->setDimension(Dimension(148.0f, 42.0f));
    m_optionsBtn->setPosition(Vector3(viewport[2]/2.0f, 200.0f, 0.0f));
    if (!m_optionsBtn->initialize()) {
        std::cerr << "Could not initialize the Options Button" << std::endl;
        return false;
    }
    m_optionsBtn->setFontSize(24);
    m_optionsBtn->setLabel("OPTIONS ");

    // Initialize exit button
    m_exitBtn = new Button(boost::shared_ptr<Scene>(this));
    m_exitBtn->setDimension(Dimension(148.0f, 42.0f));
    m_exitBtn->setPosition(Vector3(viewport[2]/2.0f, 150.0f, 0.0f));
    if (!m_exitBtn->initialize()) {
        std::cerr << "Could not initialize the Exit Button" << std::endl;
        return false;
    }
    m_exitBtn->setFontSize(24);
    m_exitBtn->setLabel("EXIT ");

    // Create a King Pig
    createKingPig();

    // Create the small pigs
    createSmallPigs();

    // Initialize the background music
    GameOptions* globalOpt = GameOptions::getOptions();
    m_bgm = new AudioSource(string("bgm_main_menu"), MUSIC);
    m_bgm->setAudioFile("data/audio/main_menu.ogg");
    m_bgm->setLoop(true);   
    m_bgm->initialize();
    m_bgm->setVolume(globalOpt->musicLevel());
    m_bgm->play();

    return true;
}

void MainMenu::prepare(float dt)
{
    // Update entities
    for (EntityIterator entity = m_entities.begin(); entity != m_entities.end(); ++entity)
    {
        (*entity)->prepare(dt);
    }

    // Update buttons
    m_arcadeBtn->prepare(dt);
    m_survivalBtn->prepare(dt);
    m_optionsBtn->prepare(dt);
    m_exitBtn->prepare(dt);

    // Check if EXIT button has been pressed
    if (m_exitBtn->isClicked())
    {
        shutdown();
    }
    // Check if ARCADE button has been pressed
    else if (m_arcadeBtn->isClicked())
    {
        m_nextScene = new Game(m_window, ARCADE);
        m_bgm->stop();
    }
    // Check if SURVIVAL button has been pressed
    else if (m_survivalBtn->isClicked())
    {
        m_nextScene = new Game(m_window, SURVIVAL);
        m_bgm->stop();
    }
    // Check if OPTIONS button has been pressed
    else if (m_optionsBtn->isClicked())
    {
        m_nextScene = new OptionsScreen(m_window);
        m_bgm->stop();
    }    
}

void MainMenu::render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //Load the identity matrix (reset to the default position and orientation)
    glLoadIdentity();

    // Render background
    m_background->render();

    // Render entities
    for (ConstEntityIterator entity = m_entities.begin(); entity != m_entities.end(); ++entity)
    {
        (*entity)->render();
        (*entity)->postRender();
    }

    // Render title
    m_font->printString("I HATE", 
                        (m_screenSize.width / 2.0f) - 85.0f, 
                        (m_screenSize.height / 2.0f) + 150.0f,
                        Color(1.0f, 0.5f, 0.0f, 1.0f));
    m_font->printString("ANGRY BIRDS", 
                        (m_screenSize.width / 2.0f) - 190.0f, 
                        (m_screenSize.height / 2.0f) + 60.0f,
                        Color(1.0f, 0.5f, 0.0f, 1.0f));

    // Render buttons
    m_arcadeBtn->render();
    m_survivalBtn->render();
    m_optionsBtn->render();
    m_exitBtn->render();
}

void MainMenu::shutdown()
{
    m_bgm->stop();
    m_nextScene = NULL;
}

void MainMenu::onResize(int width, int height)
{
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0, width, 0, height, -1, 1);
    m_screenSize.width = static_cast<float> (width);
    m_screenSize.height = static_cast<float> (height);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

bool MainMenu::createKingPig(void)
{
    KingPigFactory* factory = new KingPigFactory(boost::shared_ptr<Scene>(this));
    Entity* newEntity = factory->createEntity(Vector3(760.0f, 180.0f , 0.0f), Dimension(186.0f, 222.0f));

    if (!newEntity->initialize())
    {
        delete newEntity;
        std::cerr << "Could not initialize the new King Pig entity" << std::endl;
    }
    else
    {        
        registerEntity(newEntity);
    }

    delete factory;
    return true;
}

bool MainMenu::createSmallPigs(void)
{
    SimplePigFactory1* factory = new SimplePigFactory1(boost::shared_ptr<Scene>(this));
    vector<Entity*> pigs;
    pigs.push_back(factory->createEntity(Vector3(820.0f, 60.0f, 0.0f), Dimension(48.0f, 48.0f), 80.0f, 5.0f));
    pigs.push_back(factory->createEntity(Vector3(790.0f, 80.0f, 0.0f), Dimension(48.0f, 48.0f), 110.0f, 4.0f));
    pigs.push_back(factory->createEntity(Vector3(860.0f, 75.0f, 0.0f), Dimension(48.0f, 48.0f), 120.0f, 6.0f));

    vector<Entity*>::iterator it;
    for (it = pigs.begin(); it<pigs.end(); it++)
    {
        if (!(*it)->initialize())
        {
            delete (*it);
            std::cerr << "Could not initialize the new King Pig entity" << std::endl;
            return false;
        }
        else
        {        
            registerEntity(*it);
        }
    }

    delete factory;
    return true;
}
